iT邦幫忙

2024 iThome 鐵人賽

DAY 14
1
Kubernetes

都什麼年代了,還在學 Kubernetes系列 第 14

學 Kubernetes 的第十四天 - Storage - emptyDir & hostPath

  • 分享至 

  • xImage
  •  

本章節將深入探討兩種常見的卷類型:emptyDirhostPath。這兩者雖然概念簡單,但各自針對臨時緩存持久化儲存提供了不同的解決方案,滿足了不同的應用場景需求。透過理解這兩種卷的特性與使用方法,將能更有效地設計、部署及管理 Kubernetes 應用。

emptyDir

emptyDir 是 Kubernetes 中的一種 Volume 類型。當一個 Pod 被指派到節點上運行時,emptyDir Volume 會被創建,並在 Pod 的整個生命周期內存在。一旦該 Pod 被刪除,emptyDir 中的數據也會隨之消失。

應用場景

  1. 臨時緩存:作為一個應用的臨時緩存,數據在 Pod 的生命周期結束後不再需要。
  2. 數據處理中間存儲:用於在數據處理流水線中存儲中間結果,這些結果不需要在 Pod 之外保存。
  3. 多容器數據共享:當一個 Pod 內的多個容器需要共享某些臨時數據時,emptyDir 提供了一個簡單的解決方案。

組態檔案說明

以下是一個使用 emptyDir 的 Kubernetes 組態檔範例:

apiVersion: v1
kind: Pod
metadata:
  name: emptydir-demo
spec:
  containers:
  - name: container1
    image: busybox
    command: [ "sh", "-c", "echo Hello from container1 > /data/message && sleep 3600" ]
    volumeMounts:
    - mountPath: /data
      name: shared-data
  - name: container2
    image: busybox
    command: [ "sh", "-c", "cat /data/message && sleep 3600" ]
    volumeMounts:
    - mountPath: /data
      name: shared-data
  volumes:
  - name: shared-data
    emptyDir: {}
  • apiVersion: v1:指定使用的 Kubernetes API 版本為 v1。
  • kind: Pod:指定這個資源的類型是 Pod。
  • metadata
    • name: emptydir-demo:Pod 的名稱是 emptydir-demo
  • spec
    • containers:定義 Pod 內的容器。

      • name: container1:第一個容器的名稱是 container1

      • image: busybox:使用 busybox 這個 Docker 鏡像來啟動容器。

      • command:容器啟動時執行的命令。這裡的命令是將訊息寫入 /data/message,然後進入休眠。

      • volumeMounts:將名為 shared-data 的卷掛載到容器內的 /data 路徑。

      • name: container2:第二個容器的名稱是 container2

      • image: busybox:使用 busybox 這個 Docker 鏡像來啟動容器。

      • command:容器啟動時執行的命令。這裡的命令是讀取 /data/message 的內容,然後進入休眠。

      • volumeMounts:將名為 shared-data 的卷掛載到容器內的 /data 路徑。

    • volumes:定義 Pod 使用的卷。

      • name: shared-data:卷的名稱是 shared-data
      • emptyDir: {}:使用 emptyDir 作為卷的類型,這是一個臨時目錄,可以在兩個容器之間共享數據。

在這個範例中,我們定義了一個名為 emptydir-demo 的 Pod,該 Pod 包含兩個容器 container1container2。這兩個容器都掛載了一個名為 shared-dataemptyDir Volume 到 /data 路徑。

  • container1 會在 /data/message 中寫入一個訊息。
  • container2 則會從 /data/message 中讀取該訊息。

這個設計允許這兩個容器共享數據,而 emptyDir 提供了一個簡單的機制來實現這一點。這個 emptyDir Volume 是臨時的,當 Pod 被刪除時,所有數據都會消失。

實作: 普通的 emptyDir

組態檔案: emptyDir.yaml

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - name: example-container
    image: nginx
    volumeMounts:
    - name: emptydir-volume
      mountPath: /usr/share/nginx/html
  volumes:
  - name: emptydir-volume
    emptyDir: {}  # 使用普通的 emptyDir
  • spec.containers[].volumeMounts:容器的卷掛載配置。

    • name: emptydir-volume:這個容器掛載的卷名稱是 emptydir-volume
    • mountPath: /usr/share/nginx/html:容器內的掛載點為 /usr/share/nginx/html
  • spec.volumes:定義這個 Pod 使用的卷。

    • name: emptydir-volume:卷的名稱是 emptydir-volume
    • emptyDir: {}:使用普通的 emptyDir 作為卷的類型,表示一個臨時空目錄,當 Pod 被刪除時,這個目錄的數據將會消失。
  • 部署 Pod

kubectl apply -f emptyDir.yaml

檢查數據

  • 進入容器
kubectl exec -it example-pod -- /bin/sh
  • 在容器內創建文件:
echo "Hello, emptyDir!" > /usr/share/nginx/html/testfile.txt
  • 退出容器並刪除 Pod,然後再次創建相同的 Pod,進入容器檢查是否能找到剛才創建的文件。
kubectl delete pod example-pod
kubectl apply -f emptyDir.yaml
kubectl exec -it example-pod -- /bin/sh
  • 檢查文件是否存在:
cat /usr/share/nginx/html/testfile.txt
---
cat: /usr/share/nginx/html/testfile.txt: No such file or directory

文件不存在,這表明 emptyDir 卷是臨時的,隨著 Pod 的刪除,數據也被刪除了。

實作: 使用內存的 emptyDir

在 Kubernetes 中,emptyDir 可以配置為使用節點的內存 (memory) 來存儲數據,這樣可以提高 I/O 性能。

組態檔案: emptydir-memory.yaml

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - name: example-container
    image: nginx
    volumeMounts:
    - name: emptydir-memory
      mountPath: /usr/share/nginx/html
  volumes:
  - name: emptydir-memory
    emptyDir:
      medium: Memory  # 指定使用內存

  • 部署 Pod
kubectl apply -f emptydir-memory.yaml
  • 進入容器
kubectl exec -it example-pod -- /bin/sh

檢查內存使用情況

進入容器後,可以通過以下幾個方法檢查 emptyDir 是否使用了記憶體:

方法一:檢查文件系統類型
  • 檢查 emptyDir 掛載點的文件系統類型
df -h /usr/share/nginx/html
---
Filesystem      Size  Used Avail Use% Mounted on
tmpfs            32G     0   32G   0% /usr/share/nginx/html

如果掛載點顯示類型為 tmpfs,那麼它使用的是內存。

方法二:寫入數據並檢查內存使用
  • 在容器外,使用以下指令檢查內存
kubectl top pod
---
NAME          CPU(cores)   MEMORY(bytes)
example-pod   0m           12Mi
  • 在容器內,在掛載點上創建一個大文件,然後檢查節點上的內存使用情況。
dd if=/dev/zero of=/usr/share/nginx/html/testfile bs=1M count=100
  • 退出容器,然後使用以下指令檢查內存
kubectl top pod
---
NAME          CPU(cores)   MEMORY(bytes)
example-pod   2m           113Mi

內存使用量顯著增加,說明 emptyDir 正在使用內存。


hostPath

hostPath 是 Kubernetes 中的一種 Volume 類型,允許你將 Kubernetes 節點上的檔案或目錄掛載到 Pod 中的容器內。當你使用 hostPath 時,你可以指定節點上的一個具體路徑,Pod 啟動後,該路徑會被掛載到容器內的指定路徑中。

為什麼需要 hostPath

hostPath 的主要用途是允許容器直接訪問 Kubernetes 節點上的文件系統資源。這在一些情況下非常有用,例如:

  • 存取節點上的系統檔案:某些應用程式可能需要存取節點上的特定系統檔案或日誌檔案。
  • 數據共享:在多個 Pod 或應用程式之間共享特定的檔案或目錄。
  • 持久性數據:在 Pod 重啟後,仍然希望保留某些數據(假設節點未被重啟或刪除)。

應用場景

  1. 日誌存取:應用程式可以使用 hostPath 來存取和分析節點上的日誌檔案。
  2. 執行容器化的系統工具:某些工具可能需要存取主機系統上的特定檔案或目錄,例如 Docker 套件。
  3. 持久性數據存儲:在不使用外部持久性存儲(如 NFS、PV)的情況下,可以使用 hostPath 來確保數據在 Pod 重啟後仍然存在。

注意事項

  • 安全性hostPath 可能使容器獲得過高的權限,增加安全風險。應在必要情況下使用,並考慮其他更安全的存儲選項。
  • 非跨節點hostPath 所掛載的目錄或文件僅存在於 Kubernetes 集群中的某個特定節點上,而不是在整個集群中的所有節點上共享。因此,如果 Pod 因某種原因(例如節點故障、負載均衡)被重新調度到另一個節點,原來的 hostPath 路徑將不再可用,因為這個路徑不存在於新節點上。

組態檔案說明

以下是一個使用 hostPath 的 Kubernetes 組態檔範例:

apiVersion: v1
kind: Pod
metadata:
  name: hostpath-demo
spec:
  containers:
  - name: container1
    image: busybox
    command: [ "sh", "-c", "ls /mnt/hostpath && sleep 3600" ]
    volumeMounts:
    - mountPath: /mnt/hostpath
      name: my-hostpath
  volumes:
  - name: my-hostpath
    hostPath:
      path: /data
      type: Directory
  • apiVersion: v1:指定使用的 Kubernetes API 版本為 v1。
  • kind: Pod:指定這個資源的類型是 Pod。
  • metadata
    • name: hostpath-demo:Pod 的名稱是 hostpath-demo
  • spec
    • containers:定義 Pod 內的容器。
      • name: container1:容器的名稱是 container1
      • image: busybox:使用 busybox 這個 Docker 鏡像來啟動容器。
      • command:容器啟動時執行的命令,這裡是列出 /mnt/hostpath 目錄的內容,然後進入休眠。
      • volumeMounts:將名為 my-hostpath 的卷掛載到容器內的 /mnt/hostpath 路徑。
    • volumes:定義 Pod 使用的卷。
      • name: my-hostpath:卷的名稱是 my-hostpath
      • hostPath:指定卷的來源為主機路徑。
        • path: /data:主機上的路徑為 /data
        • type: Directory:指定該路徑的類型為目錄 (Directory)。

在這個範例中,我們定義了一個名為 hostpath-demo 的 Pod,該 Pod 包含一個容器 container1。我們使用 hostPath Volume 將節點上的 /data 目錄掛載到容器內的 /mnt/hostpath 路徑中。

  • path:指定主機上的目錄或檔案路徑。這個範例中為 /data
  • type:指定 hostPath 的類型,如 Directory(目錄)、File(檔案)等。這個範例中使用 Directory

這個設計允許容器存取和使用節點上的本地資源,這在需要直接操作主機文件系統的情況下特別有用。

實作

組態檔案: hostPath.yaml

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  nodeName: wslkind-worker2 # 調度 Pod 到特定的節點
  containers:
  - name: example-container
    image: nginx
    volumeMounts:
    - name: hostpath-volume
      mountPath: /usr/share/nginx/html  # 容器內的掛載點
  volumes:
  - name: hostpath-volume
    hostPath:
      path: /data  # 節點上的路徑
      type: DirectoryOrCreate  # 如果目錄不存在,則自動創建
  • 部署 Pod
kubectl apply -f hostPath.yaml
  • 進入容器
kubectl exec -it example-pod -- /bin/sh
  • 在容器內創建文件:
echo "Hello, hostPath!" > /usr/share/nginx/html/testfile.txt
  • 退出容器並刪除 Pod,然後再次創建相同的 Pod,進入容器檢查是否能找到剛才創建的文件。
kubectl delete pod example-pod
kubectl apply -f hostPath.yaml
kubectl exec -it example-pod -- /bin/sh
  • 檢查文件是否存在:
cat /usr/share/nginx/html/testfile.txt
---
Hell: not found!

文件存在,這表明 hostPath 卷是持久儲存,儘管刪除了掛載的 Pod,數據依然存留。

小結

emptyDirhostPath 各有其獨特的特性和適用場景。在選擇使用哪種卷時,應根據應用的需求、數據持久化要求以及安全性考量來做出決策。

  • emptyDir 主要用於臨時緩存、數據處理中間存儲和多容器數據共享,它提供了一個簡單的機制來共享臨時數據。

  • hostPath 允許容器直接存取節點上的文件系統資源,這在一些需要存取特定系統文件或日誌文件、數據共享以及持久性數據存儲的場景下非常有用。然而,hostPath 也可能帶來安全風險,需要謹慎使用。


上一篇
學 Kubernetes 的第十三天 - Storage - Volume
下一篇
學 Kubernetes 的第十五天 - Storage - ConfigMap
系列文
都什麼年代了,還在學 Kubernetes37
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言